﻿using HslCommunication.ModBus;
using Sunny.UI;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using ConfigHelper = qzjxm.Helper.ConfigHelper;
using HZH_Controls.Controls;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace qzjxm
{
    public partial class Form1 : UIForm
    {
        private ModbusRtu _modbusRtu;
        private CancellationTokenSource cts = new CancellationTokenSource();
        private bool _isCollect;
        private BlockingCollection<short[]> _collection = new BlockingCollection<short[]>(500);

        public Form1()
        {
            InitializeComponent();
            btnRealTimeData.BackColor = Color.Green;

            InitConfig();
            InitModbus();
            InitUi();
        }

        #region 从 INI 文件中读取配置，并赋值给 ConfigHelper.Current 的各个属性
        private void InitConfig()
        {
            ConfigHelper.Current.Load();
        }
        #endregion

        #region 初始化RTU
        // 初始化Modbus RTU通信
        private void InitModbus()
        {
            _modbusRtu = new ModbusRtu();
            _modbusRtu.SerialPortInni(sp =>
            {
                sp.PortName = ConfigHelper.Current.ProtName;
                sp.BaudRate = ConfigHelper.Current.BaudRate;
                sp.DataBits = ConfigHelper.Current.DataBits;
                sp.StopBits = ConfigHelper.Current.StopBits;
                sp.Parity = ConfigHelper.Current.Parity;
                sp.RtsEnable = ConfigHelper.Current.RtsEnable;
            });
            _modbusRtu.ReceiveTimeOut = ConfigHelper.Current.ReceiveTimeOut;
            _modbusRtu.Station = ConfigHelper.Current.Station;
            _modbusRtu.DataFormat = ConfigHelper.Current.DataFormat;
            _modbusRtu.AddressStartWithZero = ConfigHelper.Current.AddressStartWithZero;
            _modbusRtu.IsClearCacheBeforeRead = ConfigHelper.Current.IsClearCacheBeforeRead;
            _modbusRtu.Crc16CheckEnable = ConfigHelper.Current.Crc16CheckEnable;
        }
        #endregion

        #region 点击连接
        //启动按钮
        private void btnConnect_Click_1(object sender, EventArgs e)
        {
            try
            {
                var result = _modbusRtu.Open();
                if (result.IsSuccess)
                {
                    MessageBox.Show("连接成功", "提示", MessageBoxButtons.OK);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        #endregion

        #region 点击实时读取：生产者
        //实时采集数据按钮
        private void btnRealTimeData_Click(object sender, EventArgs e)
        {
            if (!_modbusRtu.IsOpen())
            {
                btnRealTimeData.BackColor = Color.Green;
                MessageBox.Show("请先连接设备", "提示", MessageBoxButtons.OK);
                return;
            }

            btnRealTimeData.BackColor = Color.Red;
            _isCollect = !_isCollect;

            if (_isCollect) //如果已经开始采集
            {
                btnRealTimeData.Text = "开始采集";
                btnRealTimeData.BackColor = Color.Green;

                cts?.Cancel();
            }
            else //如果没有开始采集，就开始采集数据
            {
                btnRealTimeData.Text = "停止采集";
                btnRealTimeData.BackColor = Color.Red;

                cts = new CancellationTokenSource();
                Task.Run(async () =>
                {
                    //cts.IsCancellationRequested ：可以用来判断整个取消机制是否触发
                    //cts.Token.IsCancellationRequested ：表示这个 token 是否检测到取消,用于在任务、线程或异步操作内部判断是否要提前退出。
                    while (!cts.Token.IsCancellationRequested)
                    {
                        try
                        {
                            //// 异步读取保持寄存器
                            // 参数说明：
                            // "1" - 起始地址（寄存器地址0，对应40001） 
                            // 9 - 读取数量（读取10个连续的寄存器）
                            var result = await _modbusRtu.ReadInt16Async("1", 9);

                            if (result.IsSuccess)
                            {
                                if (!_collection.TryAdd(result.Content))
                                {
                                    _collection.TryTake(out var data);
                                }
                            }

                            await Task.Delay(10);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message);
                        }
                    }
                }, cts.Token);

            }
        }
        #endregion

        #region 使用读取到的数据：消费者
        //消费者
        private void InitUi()
        {
            Task.Run(async () =>
            {
                while (true)
                {
                    _collection.TryTake(out var data);

                    if (data != null)
                    {
                        Invoke(new Action(() =>
                        {
                            if (data.Length > 8)
                            {
                                //重量1
                                ucMeterWeight1.Value = data[0];
                                //重量2
                                ucMeterWeight2.Value = data[1];

                                //刷新界面上的缺料方向
                                ucArrowLoss.Direction = data[7] == 0
                                    ? HZH_Controls.Controls.ArrowDirection.Left
                                    : HZH_Controls.Controls.ArrowDirection.Right;
                                //刷新温度计
                                ucThermometer1.Value = data[8];
                                //分度
                                ucThermometer2.Value = data[3];
                            }
                        }));
                    }
                    await Task.Delay(10);
                }
            });
        }
        #endregion
    }
}
